package com.longway.core.toolbox.wdp.api;

import java.util.Map;
import java.util.concurrent.Callable;

import com.jfinal.kit.JsonKit;
import com.jfinal.kit.Ret;
import com.jfinal.kit.StrKit;
import com.longway.core.toolbox.cache.ICache;
import com.longway.core.toolbox.utils.HttpUtils;
import com.longway.core.toolbox.utils.RetryUtils;
import com.longway.core.toolbox.wdp.WdpConfig;
import com.longway.core.toolbox.wdp.WdpConfigKit;

public class ComponentAccessTokenApi {
    private static String url = "https://api.weixin.qq.com/cgi-bin/component/api_component_token";

    private static final String cachePrefix = "component:";

    /**
     * 从缓存中获取 ComponentAccessToken，如果未取到或者ComponentAccessToken 不可用则先更新再获取
     * @return ComponentAccessToken componentAccessToken
     */
    public static ComponentAccessToken getComponentAccessToken() {
    	WdpConfig wdp = WdpConfigKit.getWdpConfig();
    	ComponentAccessToken result;// = getAvailableComponentAccessToken(wdp);
        //if (result == null) {
            synchronized(ComponentAccessTokenApi.class) {
                result = getAvailableComponentAccessToken(wdp);
                if (result == null) {
                    result = refreshComponentAccessToken(wdp);
                }
            }
        //}
        return result;
    }
    
    private static ComponentAccessToken getAvailableComponentAccessToken(WdpConfig wc) {
        ICache accessTokenCache = ApiConfigKit.getAccessTokenCache();
        String accessTokenJson = accessTokenCache.get(cachePrefix + wc.getAppId());
        if (StrKit.notBlank(accessTokenJson)) {
        	ComponentAccessToken result = new ComponentAccessToken(accessTokenJson);
            if (result != null && result.isAvailable()) {
                return result;
            }
        }
        return null;
    }

    /**
     * 直接获取 componentAccessToken 字符串，方便使用
     * @return String componentAccessToken
     */
    public static String getComponentAccessTokenStr() {
    	ComponentAccessToken cat = getComponentAccessToken();
    	if(cat!=null && cat.isAvailable()){
    		return getComponentAccessToken().getComponentAccessToken();
    	}else{
        	throw new RuntimeException(cat.getErrorMsg());
        }
    }

    /**
     * 无条件强制更新componentAccessToken 值，不再对 cache 中的 token 进行判断
     * @param WdpConfig
     * @return ComponentAccessToken
     */
    private static ComponentAccessToken refreshComponentAccessToken(WdpConfig wdp) {
        String appId = wdp.getAppId();
        String appSecret = wdp.getAppSecret();
        final Map<String, String> queryParas = Ret.create("component_appid", appId)
        		.set("component_appsecret", appSecret)
        		.set("component_verify_ticket", wdp.getComponentVerifyTicket());
        // 最多三次请求
        ComponentAccessToken result = RetryUtils.retryOnException(3, new Callable<ComponentAccessToken>() {
            @Override
            public ComponentAccessToken call() throws Exception {
                String json = HttpUtils.post(url, JsonKit.toJson(queryParas)); //HttpUtils.post(url, JsonKit.toJson(queryParas));
                return new ComponentAccessToken(json);
            }
        });

        if (null != result && result.isAvailable()) {
            ICache accessTokenCache = ApiConfigKit.getAccessTokenCache();
            accessTokenCache.set(cachePrefix + wdp.getAppId(), result.getCacheJson());
        }
        return result;
    }

}
